package com.hsurosy.hsuchain.nft.admin.controller;

import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import com.hsurosy.hsuchain.nft.admin.infrastucture.exception.AdminException;
import com.hsurosy.hsuchain.nft.admin.params.AdminLoginParam;
import com.hsurosy.hsuchain.nft.admin.vo.AdminLoginVO;
import com.hsurosy.hsuchain.nft.api.user.constant.UserRole;
import com.hsurosy.hsuchain.nft.api.user.request.UserPageQueryRequest;
import com.hsurosy.hsuchain.nft.api.user.request.UserQueryRequest;
import com.hsurosy.hsuchain.nft.api.user.response.UserOperatorResponse;
import com.hsurosy.hsuchain.nft.api.user.response.UserQueryResponse;
import com.hsurosy.hsuchain.nft.api.user.response.data.UserInfo;
import com.hsurosy.hsuchain.nft.api.user.service.UserFacadeService;
import com.hsurosy.hsuchain.nft.api.user.service.UserManageFacadeService;
import com.hsurosy.hsuchain.nft.base.response.PageResponse;
import com.hsurosy.hsuchain.nft.web.util.MultiResultConvertor;
import com.hsurosy.hsuchain.nft.web.vo.MultiResult;
import com.hsurosy.hsuchain.nft.web.vo.Result;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.web.bind.annotation.*;

import static com.hsurosy.hsuchain.nft.admin.infrastucture.exception.AdminErrorCode.ADMIN_USER_NOT_EXIST;

/**
 * 用户后台管理控制器
 *
 * @Author Hsu琛君珩
 * @Date 2024-10-05 19:19
 * @Description
 * @Version: v1.0.0
 */
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("admin/user")
@CrossOrigin(origins = "*")
public class UserAdminController {

    /**
     * 通过 Dubbo 引入 UserFacadeService 服务，用于处理用户相关的操作。
     */
    @DubboReference(version = "1.0.0")
    private UserFacadeService userFacadeService;

    /**
     * 通过 Dubbo 引入 UserManageFacadeService 服务，用于处理用户管理相关的操作（如冻结、解冻用户）。
     */
    @DubboReference(version = "1.0.0")
    private UserManageFacadeService userManageFacadeService;

    /**
     * 登录会话的默认超时时间：7天。
     */
    private static final Integer DEFAULT_LOGIN_SESSION_TIMEOUT = 60 * 60 * 24 * 7;

    /**
     * 获取当前登录用户的信息。
     *
     * @return 返回当前登录的用户信息
     */
    @GetMapping("/getUserInfo")
    public Result<UserInfo> getUserInfo() {
        String userId = (String) StpUtil.getLoginId(); // 获取当前登录用户的ID
        UserQueryRequest request = new UserQueryRequest(Long.valueOf(userId)); // 构建用户查询请求
        UserQueryResponse<UserInfo> userQueryResponse = userFacadeService.query(request); // 查询用户信息
        UserInfo userInfo = userQueryResponse.getData();

        // 如果用户信息不存在，则抛出异常
        if (userInfo == null) {
            throw new AdminException(ADMIN_USER_NOT_EXIST);
        }
        return Result.success(userInfo); // 返回成功响应，包含用户信息
    }

    /**
     * 分页查询用户列表。
     *
     * @param state 用户状态
     * @param keyWord 搜索关键字
     * @param pageSize 每页大小
     * @param currentPage 当前页码
     * @return 返回用户列表
     */
    @GetMapping("/userList")
    public MultiResult<UserInfo> userList(@NotBlank String state, String keyWord, int pageSize, int currentPage) {
        UserPageQueryRequest userPageQueryRequest = new UserPageQueryRequest(); // 构建分页查询请求
        userPageQueryRequest.setState(state);
        userPageQueryRequest.setKeyWord(keyWord);
        userPageQueryRequest.setCurrentPage(currentPage);
        userPageQueryRequest.setPageSize(pageSize);
        PageResponse<UserInfo> pageResponse = userFacadeService.pageQuery(userPageQueryRequest); // 执行查询
        return MultiResultConvertor.convert(pageResponse); // 返回多条结果
    }

    /**
     * 管理员登录。
     *
     * @param loginParam 登录参数（包括手机号和密码）
     * @return 返回登录成功后的用户信息和 Token
     */
    @PostMapping("/login")
    public Result<AdminLoginVO> login(@Valid @RequestBody AdminLoginParam loginParam) {

        // 查询用户信息
        UserQueryRequest userQueryRequest = new UserQueryRequest(loginParam.getTelephone(), loginParam.getPassword());
        UserQueryResponse<UserInfo> userQueryResponse = userFacadeService.query(userQueryRequest);
        UserInfo userInfo = userQueryResponse.getData();

        // 如果用户不存在或者不是管理员，不能登录
        if (userInfo == null || !userInfo.getUserRole().equals(UserRole.ADMIN)) {
            return Result.error(ADMIN_USER_NOT_EXIST.getCode(), ADMIN_USER_NOT_EXIST.getMessage());
        } else {
            // 执行登录操作，设置 Cookie 和会话超时时间
            StpUtil.login(userInfo.getUserId(), new SaLoginModel().setIsLastingCookie(loginParam.getRememberMe()).setTimeout(DEFAULT_LOGIN_SESSION_TIMEOUT));
            StpUtil.getSession().set(userInfo.getUserId().toString(), userInfo); // 将用户信息存入会话
            AdminLoginVO loginVO = new AdminLoginVO(userInfo); // 构建登录响应对象
            return Result.success(loginVO); // 返回成功响应
        }
    }

    /**
     * 管理员登出。
     *
     * @return 返回登出操作结果
     */
    @PostMapping("/logout")
    public Result<Boolean> logout() {
        StpUtil.logout(); // 执行登出操作
        return Result.success(true); // 返回成功响应
    }

    /**
     * 冻结用户账号。
     *
     * @param userId 需要冻结的用户ID
     * @return 返回冻结操作结果
     */
    @PostMapping("/freeze")
    public Result<UserOperatorResponse> freeze(@Valid Long userId) {
        String adminUserId = (String) StpUtil.getLoginId(); // 获取当前登录的管理员ID

        // 查询管理员信息
        UserQueryRequest adminQueryRequest = new UserQueryRequest(Long.valueOf(adminUserId));
        UserQueryResponse<UserInfo> userQueryResponse = userFacadeService.query(adminQueryRequest);
        UserInfo userInfo = userQueryResponse.getData();

        // 如果管理员用户不存在或者用户角色不是管理员，返回错误
        if (userInfo == null || !userInfo.getUserRole().equals(UserRole.ADMIN)) {
            return Result.error(ADMIN_USER_NOT_EXIST.getCode(), ADMIN_USER_NOT_EXIST.getMessage());
        }

        // 冻结用户操作
        var res = userManageFacadeService.freeze(userId);

        // 重新查出用户信息，更新登录的 session，确保用户权限实时更新
        refreshUserInSession(userId);

        return Result.success(res); // 返回冻结结果
    }

    /**
     * 解冻用户账号。
     *
     * @param userId 需要解冻的用户ID
     * @return 返回解冻操作结果
     */
    @PostMapping("/unfreeze")
    public Result<UserOperatorResponse> unfreeze(@Valid Long userId) {
        String adminUserId = (String) StpUtil.getLoginId(); // 获取当前登录的管理员ID

        // 查询管理员信息
        UserQueryRequest adminQueryRequest = new UserQueryRequest(Long.valueOf(adminUserId));
        UserQueryResponse<UserInfo> userQueryResponse = userFacadeService.query(adminQueryRequest);
        UserInfo userInfo = userQueryResponse.getData();

        // 如果管理员用户不存在或者用户角色不是管理员，返回错误
        if (userInfo == null || !userInfo.getUserRole().equals(UserRole.ADMIN)) {
            return Result.error(ADMIN_USER_NOT_EXIST.getCode(), ADMIN_USER_NOT_EXIST.getMessage());
        }

        // 解冻用户操作
        var res = userManageFacadeService.unfreeze(userId);

        // 重新查出用户信息，更新登录的 session，确保用户权限实时更新
        refreshUserInSession(userId);

        return Result.success(res); // 返回解冻结果
    }

    /**
     * 更新登录用户在会话中的信息。
     *
     * @param userId 需要更新信息的用户ID
     */
    private void refreshUserInSession(Long userId) {
        UserQueryRequest userQueryRequest = new UserQueryRequest(userId); // 构建用户查询请求
        UserQueryResponse userQueryResponse = userFacadeService.query(userQueryRequest); // 查询用户信息
        StpUtil.getSession().set(userId.toString(), userQueryResponse.getData()); // 更新会话中的用户信息
    }

}
